home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 223 / emacssrc / cursor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-17  |  11.0 KB  |  521 lines

  1. /*
  2.  * file basic.c:
  3.  *
  4.  * The routines in this file
  5.  * move the cursor around on the screen.
  6.  * They compute a new value for the cursor, then
  7.  * adjust ".". The display code always updates the
  8.  * cursor location, so only moves between lines,
  9.  * or functions that adjust the top line in the window
  10.  * and invalidate the framing, are hard.
  11.  */
  12. #include    <stdio.h>
  13. #include    "ed.h"
  14.  
  15. extern int enlrg_kbuf();    /* mb: added, it's in line.c */
  16.  
  17. static char nms[] = "No mark set in this window";
  18. static char nem[] = "Not enough memory. Try a smaller region";
  19.  
  20. /*
  21.  * Move the cursor to the
  22.  * beginning of the current line.
  23.  * Trivial.
  24.  */
  25. gotobol(f, n)
  26.     {
  27.     curwp->w_doto = 0;
  28.     return(TRUE);
  29.     }
  30.  
  31. /*
  32.  * Move the cursor backwards by
  33.  * "n" characters. If "n" is less than
  34.  * zero call "forwchar" to actually do the
  35.  * move. Otherwise compute the new cursor
  36.  * location. Error if you try and move
  37.  * out of the buffer. Set the flag if the
  38.  * line pointer for dot changes.
  39.  */
  40. backchar(f, n)
  41.     register int    n;
  42.     {
  43.     register LINE    *lp;
  44.  
  45.     if (n < 0)
  46.         return (forwchar(f, -n));
  47.     while (n--)
  48.         {
  49.         if (curwp->w_doto == 0)
  50.             {
  51.             if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  52.                 return (FALSE);
  53.             curwp->w_dotp  = lp;
  54.             curwp->w_doto  = llength(lp);
  55.             curwp->w_flag |= WFMOVE;
  56.             }
  57.         else
  58.             curwp->w_doto--;
  59.         }
  60.     return (TRUE);
  61.     }
  62.  
  63. /*
  64.  * Move the cursor to the end
  65.  * of the current line. Trivial.
  66.  * No errors.
  67.  */
  68. gotoeol(f, n)
  69.     {
  70.     curwp->w_doto  = llength(curwp->w_dotp);
  71.     return (TRUE);
  72.     }
  73.  
  74. /*
  75.  * Move the cursor forwwards by
  76.  * "n" characters. If "n" is less than
  77.  * zero call "backchar" to actually do the
  78.  * move. Otherwise compute the new cursor
  79.  * location, and move ".". Error if you
  80.  * try and move off the end of the
  81.  * buffer. Set the flag if the line pointer
  82.  * for dot changes.
  83.  */
  84. forwchar(f, n)
  85. register int    n;
  86.     {
  87.     if (n < 0)
  88.         return (backchar(f, -n));
  89.     while (n--)
  90.         {
  91.         if (curwp->w_doto == llength(curwp->w_dotp))
  92.             {
  93.             if (curwp->w_dotp == curbp->b_linep)
  94.                 return (FALSE);
  95.             curwp->w_dotp  = lforw(curwp->w_dotp);
  96.             curwp->w_doto  = 0;
  97.             curwp->w_flag |= WFMOVE;
  98.             }
  99.         else
  100.             curwp->w_doto++;
  101.         }
  102.     return (TRUE);
  103.     }
  104.  
  105. /*
  106.  * Goto the beginning of the buffer.
  107.  * Massive adjustment of dot. This is considered
  108.  * to be hard motion; it really isn't if the original
  109.  * value of dot is the same as the new value of dot.
  110.  * Normally bound to "M-<".
  111.  */
  112. gotobob(f, n)
  113.     {
  114.     curwp->w_dotp  = lforw(curbp->b_linep);
  115.     curwp->w_doto  = 0;
  116.     curwp->w_flag |= WFHARD;
  117.     return (TRUE);
  118.     }
  119.  
  120. /*
  121.  * Move to the end of the buffer.
  122.  * Dot is always put at the end of the
  123.  * file (ZJ). The standard screen code does
  124.  * most of the hard parts of update. Bound to 
  125.  * "M->".
  126.  */
  127. gotoeob(f, n)
  128.     {
  129.     curwp->w_dotp  = curbp->b_linep;
  130.     curwp->w_doto  = 0;
  131.     curwp->w_flag |= WFHARD;
  132.     return (TRUE);
  133.     }
  134.  
  135. /*
  136.  * Move forward by full lines.
  137.  * The last command controls how
  138.  * the goal column is set.
  139.  * Bound to "C-N". No errors are possible.
  140.  */
  141. forwline(f, n)
  142.     register int n;
  143.     {
  144.     register LINE    *dlp;
  145.  
  146.     if (n == 0)
  147.         return (TRUE);
  148.     if ((lastflag&CFCPCN) == 0)        /* Reset goal if last    */
  149.         curgoal = curcol;        /* not C-P or C-N    */
  150.     thisflag |= CFCPCN;
  151.     dlp = curwp->w_dotp;
  152.     if (n > 0)                /* mb: generalized    */
  153.         while (n-- && dlp!=curbp->b_linep)
  154.             dlp = lforw(dlp);
  155.     else
  156.         while (n++ && lback(dlp)!=curbp->b_linep)
  157.             dlp = lback(dlp);
  158.     curwp->w_dotp  = dlp;
  159.     curwp->w_doto  = getgoal(dlp);
  160.     curwp->w_flag |= WFMOVE;
  161.     return (TRUE);
  162.     }
  163.  
  164. /*
  165.  * mb: drastically simplified!
  166.  */
  167. backline(f, n)
  168.     {
  169.     return (forwline(f, -n));
  170.     }
  171.  
  172. /*
  173.  * mb: added.
  174.  */
  175. gotolinum(f, n)
  176.     {
  177.     int s;
  178.  
  179.     if ((s = gotobob(FALSE,1)) != TRUE)
  180.         return(s);
  181.     return (forwline(f, n-1));
  182.     }
  183.  
  184. /*
  185.  * This routine, given a pointer to
  186.  * a LINE, and the current cursor goal
  187.  * column, return the best choice for the
  188.  * offset. The offset is returned.
  189.  * Used by "C-N" and "C-P".
  190.  */
  191. getgoal(dlp)
  192. register LINE    *dlp;
  193.     {
  194.     register int    c;
  195.     register int    col;
  196.     register int    newcol;
  197.     register int    dbo;
  198.  
  199.     col = 0;
  200.     dbo = 0;
  201.     while (dbo < llength(dlp))
  202.         {
  203.         c = lgetc(dlp, dbo);
  204.         newcol = col;
  205.         if (c == '\t')
  206.             newcol += tabsize - (newcol % tabsize) - 1;  /* mb: */
  207.         else if (iscntrl(c))    /* (c<0x20 || c==0x7F) */
  208.             ++newcol;
  209.         ++newcol;
  210.         if (newcol > curgoal)
  211.             break;
  212.         col = newcol;
  213.         ++dbo;
  214.         }
  215.     return (dbo);
  216.     }
  217.  
  218. /*
  219.  * Scroll forward by a specified number
  220.  * of lines, or by a full page if no argument.
  221.  * Bound to "C-V". The "2" in the arithmetic on
  222.  * the window size is the overlap; this value is
  223.  * the default overlap value in ITS EMACS.
  224.  * Because this zaps the top line in the display
  225.  * window, we have to do a hard update.
  226.  */
  227. forwpage(f, n) 
  228.     register int    n;
  229.     {
  230.     register LINE    *lp;
  231.     register int    i;
  232.  
  233.     if ((f == FALSE) || (n == (-1)))
  234.         {
  235.         i = curwp->w_ntrows - 2;    /* Default scroll.    */
  236.         if (i <= 0)            /* Forget the overlap    */
  237.             i = 1;            /* if tiny window.    */
  238.         n *= i;                /* mb: n may be <0    */
  239.         }
  240. #if    CVMVAS
  241.     else                    /* Convert from pages    */
  242.         n *= curwp->w_ntrows;        /* to lines.        */
  243. #endif
  244.     lp = curwp->w_linep;
  245.     for (i=1; lp!=curwp->w_dotp; ++i)    /* mb: changed so that  */
  246.         lp = lforw(lp);            /* cursor moves with    */
  247.     curwp->w_force = i;            /* window - i is offset */
  248.     curwp->w_flag |= WFFORCE;
  249.     return (forwline(FALSE, n));        /* mb: works forw&back  */
  250.     }
  251.  
  252. /*
  253.  * mb: drastically simplified.
  254.  */
  255. backpage(f, n)
  256.     register int    f;
  257.     register int    n;
  258.     {
  259.     return (forwpage(f, -n));
  260.     }
  261.  
  262. /*
  263.  * Set the mark in the current window
  264.  * to the value of "." in the window. No errors
  265.  * are possible. Bound to "M-.".
  266.  */
  267. setmark(f, n)
  268.     {
  269.     curwp->w_markp = curwp->w_dotp;
  270.     curwp->w_marko = curwp->w_doto;
  271.     mlwrite("[Mark set]");
  272.     return (TRUE);
  273.     }
  274.  
  275. /*
  276.  * Swap the values of "." and "mark" in
  277.  * the current window. This is pretty easy, bacause
  278.  * all of the hard work gets done by the standard routine
  279.  * that moves the mark about. The only possible error is
  280.  * "no mark". Bound to "C-X C-X".
  281.  */
  282. swapmark(f, n)
  283.     {
  284.     register LINE    *odotp;
  285.     register int    odoto;
  286.  
  287.     if (curwp->w_markp == NULL)
  288.         {
  289.         mlwrite(nms);
  290.         return (FALSE);
  291.         }
  292.     odotp = curwp->w_dotp;
  293.     odoto = curwp->w_doto;
  294.     curwp->w_dotp  = curwp->w_markp;
  295.     curwp->w_doto  = curwp->w_marko;
  296.     curwp->w_markp = odotp;
  297.     curwp->w_marko = odoto;
  298.     curwp->w_flag |= WFMOVE;
  299.     return (TRUE);
  300.     }
  301.  
  302.  
  303. /* file region.c:
  304.  *
  305.  * The routines in this file
  306.  * deal with the region, that magic space
  307.  * between "." and mark. Some functions are
  308.  * commands. Some functions are just for
  309.  * internal use.
  310.  */
  311.  
  312.  
  313. /*
  314.  * Kill the region. Ask "getregion"
  315.  * to figure out the bounds of the region.
  316.  * Move "." to the start, and kill the characters.
  317.  * Bound to "C-W".
  318.  */
  319. killregion(f, n)
  320.     {
  321.     register int    s;
  322.     REGION        region;
  323.  
  324.     if ((s=getregion(®ion)) != TRUE)
  325.         return (s);
  326.     if (region.r_size > 512)
  327.         mlwrite("[killing...]");
  328.     if ((lastflag&CFKILL) == 0)        /* This is a kill type    */
  329.         kdelete();            /* command, so do magic    */
  330.     thisflag |= CFKILL;            /* kill buffer stuff.    */
  331.     if (enlrg_kbuf(region.r_size) == FALSE )
  332.         {
  333.         mlwrite(nem);
  334.         return (FALSE);
  335.         }
  336.     curwp->w_dotp = region.r_linep;
  337.     curwp->w_doto = region.r_offset;
  338.     ldelete(region.r_size, TRUE);
  339.     mlwrite("[killed]");
  340.     return (TRUE);
  341.     }
  342.  
  343. /*
  344.  * Copy all of the characters in the
  345.  * region to the kill buffer. Don't move dot
  346.  * at all. This is a bit like a kill region followed
  347.  * by a yank. Bound to "M-W".
  348.  */
  349. copyregion(f, n)
  350.     {
  351.     register LINE    *linep;
  352.     register int    loffs;
  353.     register int    s;
  354.     REGION        region;
  355.  
  356.     if ((s=getregion(®ion)) != TRUE)
  357.         return (s);
  358.     if (region.r_size > 512)
  359.         mlwrite("[copying...]");
  360.     if ((lastflag&CFKILL) == 0)        /* Kill type command.    */
  361.         kdelete();
  362.     thisflag |= CFKILL;
  363.     if (enlrg_kbuf(region.r_size) == FALSE )
  364.         {
  365.         mlwrite(nem);
  366.         return (FALSE);
  367.         }
  368.     linep = region.r_linep;            /* Current line.    */
  369.     loffs = region.r_offset;        /* Current offset.    */
  370.     while (region.r_size-- > 0)
  371.         {
  372.         if (loffs == llength(linep))    /* End of line.        */
  373.             {
  374.             kinsert('\n');
  375.             linep = lforw(linep);
  376.             loffs = 0;
  377.             }
  378.         else                /* Middle of line.    */
  379.             {
  380.             kinsert(lgetc(linep, loffs));
  381.             ++loffs;
  382.             }
  383.         }
  384.     mlwrite("[copied]");
  385.     return (TRUE);
  386.     }
  387.  
  388. #if EXTRA
  389. /* mb: collapsed ucregion & lcregion.
  390.  * Lower case region. Zap all of the upper
  391.  * case characters in the region to lower case. Use
  392.  * the region code to set the limits. Scan the buffer,
  393.  * doing the changes. Call "lchange" to ensure that
  394.  * redisplay is done in all buffers. Bound to 
  395.  * "C-X C-L".
  396.  */
  397. lowerregion(f, n)
  398.     {
  399.     return (caseregion(FALSE));
  400.     }
  401.  
  402. upperregion(f, n)
  403.     {
  404.     return (caseregion(TRUE));
  405.     }
  406.  
  407. /* mb: the common portion of the two: */
  408. caseregion(f)
  409.     {
  410.     register LINE    *linep;
  411.     register int    loffs;
  412.     register int    c;
  413.     register int    s;
  414.     REGION        region;
  415.  
  416.     if ((s=getregion(®ion)) != TRUE)
  417.         return (s);
  418.     lchange(WFHARD);
  419.     linep = region.r_linep;
  420.     loffs = region.r_offset;
  421.     while (region.r_size-- > 0)
  422.         {
  423.         if (loffs == llength(linep))
  424.             {
  425.             linep = lforw(linep);
  426.             loffs = 0;
  427.             }
  428.         else
  429.             {
  430.             c = lgetc(linep, loffs);
  431.             if (f)        /* mb: uppercase region */
  432.                 {
  433.                 if (islower(c))
  434.                     lputc(linep, loffs, c^0x20);
  435.                 }
  436.             else
  437.                 {
  438.                 if (isupper(c))
  439.                     lputc(linep, loffs, c^0x20);
  440.                 }
  441.             ++loffs;
  442.             }
  443.         }
  444.     return (TRUE);
  445.     }
  446. #endif
  447.  
  448. /*
  449.  * This routine figures out the
  450.  * bounds of the region in the current window, and
  451.  * fills in the fields of the "REGION" structure pointed
  452.  * to by "rp". Because the dot and mark are usually very
  453.  * close together, we scan outward from dot looking for
  454.  * mark. This should save time. Return a standard code.
  455.  * Callers of this routine should be prepared to get
  456.  * an "ABORT" status; we might make this have the
  457.  * conform thing later.
  458.  */
  459. getregion(rp)
  460.     REGION    *rp;
  461.     {
  462.     register LINE    *flp;
  463.     register LINE    *blp;
  464.     register int    fsize;
  465.     register int    bsize;
  466.  
  467.     if (curwp->w_markp == NULL)
  468.         {
  469.         mlwrite(nms);
  470.         return (FALSE);
  471.         }
  472.     if (curwp->w_dotp == curwp->w_markp)
  473.         {
  474.         rp->r_linep = curwp->w_dotp;
  475.         if (curwp->w_doto < curwp->w_marko)
  476.             {
  477.             rp->r_offset = curwp->w_doto;
  478.             rp->r_size = curwp->w_marko-curwp->w_doto;
  479.             }
  480.         else
  481.             {
  482.             rp->r_offset = curwp->w_marko;
  483.             rp->r_size = curwp->w_doto-curwp->w_marko;
  484.             }
  485.         return (TRUE);
  486.         }
  487.     blp = curwp->w_dotp;
  488.     bsize = curwp->w_doto;
  489.     flp = curwp->w_dotp;
  490.     fsize = llength(flp)-curwp->w_doto+1;
  491.     while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep)
  492.         {
  493.         if (flp != curbp->b_linep)
  494.             {
  495.             flp = lforw(flp);
  496.             if (flp == curwp->w_markp)
  497.                 {
  498.                 rp->r_linep = curwp->w_dotp;
  499.                 rp->r_offset = curwp->w_doto;
  500.                 rp->r_size = fsize+curwp->w_marko;
  501.                 return (TRUE);
  502.                 }
  503.             fsize += llength(flp)+1;
  504.             }
  505.         if (lback(blp) != curbp->b_linep)
  506.             {
  507.             blp = lback(blp);
  508.             bsize += llength(blp)+1;
  509.             if (blp == curwp->w_markp)
  510.                 {
  511.                 rp->r_linep = blp;
  512.                 rp->r_offset = curwp->w_marko;
  513.                 rp->r_size = bsize - curwp->w_marko;
  514.                 return (TRUE);
  515.                 }
  516.             }
  517.         }
  518.     mlwrite("Bug: lost mark");
  519.     return (FALSE);
  520.     }
  521.